//
//  AppleSignInVerifier.swift
//  bayanarabic_server_v2
//
//  Created by 赵康 on 2024/11/25.
//

import Foundation
import Vapor
import JWTKit
import NIOConcurrencyHelpers

struct AppleSignInVerifier {
    // Apple开发者团队ID
    private let teamID: String
    // 应用的客户端ID (Service ID)
    private let clientID: String
    // 私钥ID
    private let keyID: String
    // 私钥路径
    private let privateKeyPath: String
    
    init(teamID: String, clientID: String, keyID: String, privateKeyPath: String) throws {
        self.teamID = teamID
        self.clientID = clientID
        self.keyID = keyID
        self.privateKeyPath = privateKeyPath
        
        // 确认私钥文件存在
        let fileManager = FileManager.default
        guard fileManager.fileExists(atPath: privateKeyPath) else {
            throw Abort(.internalServerError, reason: "Apple Sign In私钥文件不存在: \(privateKeyPath)")
        }
    }
    
    struct VerificationResult {
        let isValid: Bool
        let userID: String?
        let email: String?
        let errorMessage: String?
    }
    
    func verify(identityToken: String) async throws -> VerificationResult {
        do {
            // 记录开始验证
            print("开始验证Apple身份令牌，长度: \(identityToken.count)")
            print("令牌内容: \(identityToken)")
            
            // 尝试解码JWT Header来获取kid
            let tokenParts = identityToken.split(separator: ".")
            guard tokenParts.count == 3 else {
                print("Apple令牌格式错误: 找不到JWT的3个部分")
                return VerificationResult(isValid: false, userID: nil, email: nil, errorMessage: "令牌格式错误")
            }
            
            print("令牌部分1 (header): \(tokenParts[0])")
            print("令牌部分2 (payload): \(tokenParts[1])")
            
            let headerBase64 = tokenParts[0]
            guard let headerData = Data(base64Encoded: String(headerBase64).base64URLDecoded()) else {
                print("无法解码JWT头部")
                return VerificationResult(isValid: false, userID: nil, email: nil, errorMessage: "无法解码JWT头部")
            }
            
            do {
                if let headerJson = try JSONSerialization.jsonObject(with: headerData, options: []) as? [String: Any] {
                    print("解析到JWT头部: \(headerJson)")
                    if let kid = headerJson["kid"] as? String {
                        print("从令牌获取kid: \(kid)")
                    }
                    if let alg = headerJson["alg"] as? String {
                        print("从令牌获取算法: \(alg)")
                    }
                }
            } catch {
                print("解析JWT头部失败: \(error)")
            }
            
            // 获取JWT中的payload部分
            let payloadBase64 = tokenParts[1]
            guard let payloadData = Data(base64Encoded: String(payloadBase64).base64URLDecoded()) else {
                print("无法解码JWT payload")
                return VerificationResult(isValid: false, userID: nil, email: nil, errorMessage: "无法解码JWT payload")
            }
            
            do {
                if let payloadJson = try JSONSerialization.jsonObject(with: payloadData, options: []) as? [String: Any] {
                    print("解析到JWT payload: \(payloadJson)")
                }
            } catch {
                print("解析JWT payload失败: \(error)")
            }
            
            // 从Apple获取公钥
            print("开始从Apple获取公钥...")
            let signers = try await fetchApplePublicKeys()
            print("成功获取Apple公钥")
            
            // 解析和验证JWT令牌
            var payload: AppleIdentityToken
            do {
                payload = try signers.verify(identityToken, as: AppleIdentityToken.self)
                print("JWT令牌验证成功，获取到用户ID: \(payload.sub)")
            } catch {
                print("JWT令牌验证失败: \(error)")
                // 尝试打印更多诊断信息
                if let jwtError = error as? JWTError {
                    print("错误类型: JWTError - \(jwtError)")
                } else {
                    print("错误类型: \(type(of: error)) - \(error.localizedDescription)")
                }
                return VerificationResult(
                    isValid: false,
                    userID: nil,
                    email: nil,
                    errorMessage: "JWT令牌验证失败: \(error.localizedDescription)"
                )
            }
            
            // 验证令牌的受众ID（aud）是否与客户端ID匹配
            print("验证受众ID: 期望 \(clientID) 或 cn.bayanarabic.bayan.tingli，实际 \(payload.aud)")
            guard payload.aud == clientID || payload.aud == "cn.bayanarabic.bayan.tingli" else {
                return VerificationResult(
                    isValid: false, 
                    userID: nil, 
                    email: nil, 
                    errorMessage: "令牌的客户端ID不匹配，预期:\(clientID)，实际:\(payload.aud)"
                )
            }
            
            // 验证令牌的发行者（iss）是否是Apple
            print("验证发行者: 期望 https://appleid.apple.com，实际 \(payload.iss)")
            guard payload.iss == "https://appleid.apple.com" else {
                return VerificationResult(
                    isValid: false, 
                    userID: nil, 
                    email: nil, 
                    errorMessage: "令牌的发行者不是Apple，而是: \(payload.iss)"
                )
            }
            
            // 验证令牌是否过期
            let currentTime = Date().timeIntervalSince1970
            if let expTime = payload.exp?.timeIntervalSince1970 {
                print("验证过期时间: 当前 \(currentTime)，过期 \(expTime)")
                if currentTime > expTime {
                    return VerificationResult(
                        isValid: false, 
                        userID: nil, 
                        email: nil, 
                        errorMessage: "令牌已过期"
                    )
                }
            } else {
                print("令牌没有过期时间")
            }
            
            print("Apple身份验证成功")
            return VerificationResult(
                isValid: true,
                userID: payload.sub,
                email: payload.email,
                errorMessage: nil
            )
            
        } catch {
            print("Apple身份验证异常: \(error)")
            return VerificationResult(
                isValid: false,
                userID: nil,
                email: nil,
                errorMessage: "令牌验证异常: \(error.localizedDescription)"
            )
        }
    }
    
    // 从Apple获取公钥
    private func fetchApplePublicKeys() async throws -> JWTSigners {
        // 创建HTTP客户端
        let client = HTTPClient(eventLoopGroupProvider: .createNew)
        defer { try? client.syncShutdown() }
        
        // 创建请求获取Apple的公钥
        let request = try HTTPClient.Request(
            url: "https://appleid.apple.com/auth/keys",
            method: .GET
        )
        
        print("开始请求Apple公钥...")
        // 执行请求
        let response = try await client.execute(request: request).get()
        
        guard response.status == .ok else {
            print("Apple公钥请求失败: \(response.status)")
            throw Abort(.internalServerError, reason: "无法从Apple获取公钥，状态码: \(response.status.code)")
        }
        
        guard let body = response.body else {
            print("Apple返回的公钥数据为空")
            throw Abort(.internalServerError, reason: "Apple返回的公钥数据为空")
        }
        
        // 打印JWKS响应
        let jwksData = Data(buffer: body)
        print("收到Apple JWKS数据，长度: \(jwksData.count)")
        if let jwksString = String(data: jwksData, encoding: .utf8) {
            print("JWKS数据: \(jwksString)")
        }
        
        // 创建签名验证器
        let signers = JWTSigners()
        
        // 使用Apple的JWKS数据添加验证密钥
        if let jwksString = String(data: jwksData, encoding: .utf8) {
            do {
                try signers.use(jwksJSON: jwksString)
                print("成功加载Apple公钥")
            } catch {
                print("加载Apple公钥失败: \(error)")
                throw error
            }
        } else {
            print("无法将JWKS数据转换为字符串")
            throw Abort(.internalServerError, reason: "无法将JWKS数据转换为字符串")
        }
        
        return signers
    }
}

// Apple Identity Token的结构
struct AppleIdentityToken: JWTPayload, Codable {
    // 发行者
    var iss: String
    // 主题 (Apple用户ID)
    var sub: String
    // 受众 (客户端ID)
    var aud: String
    // 过期时间
    var exp: Date?
    // 发行时间
    var iat: Date?
    // 电子邮件
    var email: String?
    // 邮件是否经过验证
    var email_verified: Bool?
    // 是否为非真实邮箱（私有中转）
    var is_private_email: Bool?
    // 用户名（可选）
    var name: AppleNameComponents?
    // 授权时间
    var auth_time: Date?
    // 哈希值
    var c_hash: String?
    // 是否支持nonce
    var nonce_supported: Bool?
    
    func verify(using signer: JWTKit.JWTSigner) throws {
        // 基本验证已在上面的verify方法中完成
    }
}

// Apple名称字段结构
struct AppleNameComponents: Codable {
    var firstName: String?
    var lastName: String?
}

// Base64URL 解码扩展
extension String {
    func base64URLDecoded() -> String {
        var base64 = self
            .replacingOccurrences(of: "-", with: "+")
            .replacingOccurrences(of: "_", with: "/")
        
        // 添加缺失的填充字符
        if base64.count % 4 != 0 {
            base64.append(String(repeating: "=", count: 4 - base64.count % 4))
        }
        
        return base64
    }
} 
